/* cl.ext.datepicker 0.1*/
(
    function (factory) {
        if (typeof define === 'function' && define.amd) {
            define(['jquery',"ExtMoment","ClickOut"], function($) {
               factory($);
            });
        } else if (typeof module === 'object' && module.exports) {
            var momentjs = require('ExtMoment');
            var clickOutJs = require('ClickOut');
            module.exports = function( root, jQuery ) {
                if ( jQuery === undefined ) {
                    if ( typeof window !== 'undefined' ) {
                        jQuery = require('jquery');
                    }
                    else {
                        jQuery = require('jquery')(root);
                    }
                }
                factory(jQuery);
            };
        } else {
            factory(jQuery);
        }
    }(
    function ($){
        //todo 时间段，time 选择
        var defaults={
            type:"default",//default|range
            layerType:"days", //years|months|days|hours|minutes|seconds
            timeType:"date",//date|time|datetime
            direction:"",//left|right
            initValue:"",
            startValue:"",
            endValue:"",
            minDate:"",
            maxDate:"",
            isClear:false,
            addQuick:{},
            removeQuick:[],
            changeCallback:null
        };
        var $modalCommon={
            getDefaults :function () {
                return defaults
            },
            getOptions : function (element,options) {
                options=$.ExtCommon.isCheckEmpty(options)?{}:options;
                var elementData=element.data();
                var optionBase=$.ExtCommon.initMergeJson(elementData,options);
                var tempValue=element.val();
                if(!$.ExtCommon.isCheckEmpty(optionBase.initValue)){tempValue=optionBase.initValue}
                optionBase.initValue=tempValue;
                optionBase =$.ExtCommon.initMergeJson(this.getDefaults(),optionBase);
                this._getInitLayerToTime(optionBase);
                optionBase.formatOut=this._getFormatByView(optionBase);
                optionBase.operateType=this._getTypeOperateTime(optionBase.layerType);
                optionBase.rangeQuick=optionBase.type==="range"?this._getRangesQuick(optionBase):{};
                optionBase.initValue=this.initTimeFormat(optionBase.initValue,optionBase.formatOut);
                optionBase.startValue=this.initTimeFormat(optionBase.startValue,optionBase.formatOut);
                optionBase.endValue=this.initTimeFormat(optionBase.endValue,optionBase.formatOut);
                if($.ExtCommon.isCheckEmpty(optionBase.direction)){optionBase.direction=optionBase.type==="range"?"right":"left"}
                return optionBase
            },
            _getInitLayerToTime:function(optionBase){
                switch (optionBase.layerType){
                    case "years":
                    case "months":
                    case "days":
                        optionBase.timeType="date";
                        break;
                    case "hours":
                    case "minutes":
                    case "seconds":
                        optionBase.timeType=optionBase.timeType==="date"?"datetime":optionBase.timeType;
                        break;
                }
            },
            _getFormatByView:function(optionBase){
                var format="YYYY-MM-DD";
                switch (optionBase.layerType){
                    case "days":
                        format="YYYY-MM-DD";
                        break;
                    case "months":
                        format="YYYY-MM";
                        break;
                    case "years":
                        format="YYYY";
                        break;
                    case "hours":
                        format=optionBase.timeType==="time"?"HH:00":(format+" HH:00");
                        break;
                    case "minutes":
                        format=optionBase.timeType==="time"?"HH:mm":(format+" HH:mm");
                        break;
                    case "seconds":
                        format=optionBase.timeType==="time"?"HH:mm:ss":(format+" HH:mm:ss");
                        break;
                }
                return format
            },
            _getTypeOperateTime:function(type){
                var operateType="months";
                switch (type){
                    case "days":
                        operateType="months";
                        break;
                    case "months":
                        operateType="years";
                        break;
                    case "years":
                        operateType="years";
                        break;
                }
                return operateType;
            },
            _getRangesQuick:function(option){
                var dataJson={};
                if(option.type==="range"){
                    switch (option.layerType){
                        case "days":
                        case "hours":
                        case "minutes":
                        case "seconds":
                            dataJson=option.timeType==="time"?{}:{
                                "今天": [$.ExtMoment.initMoment(), $.ExtMoment.initMoment()],
                                '昨天': [$.ExtMoment.initMoment().subtract(1, 'days'), $.ExtMoment.initMoment().subtract(1, 'days')],
                                '过去7天': [$.ExtMoment.initMoment().subtract(7, 'days'), $.ExtMoment.initMoment().subtract(1, 'days')],
                                '过去30天': [$.ExtMoment.initMoment().subtract(30, 'days'), $.ExtMoment.initMoment().subtract(1, 'days')],
                                '本月': [$.ExtMoment.initMoment().startOf('month'), $.ExtMoment.initMoment().endOf('month')],
                                '上月': [$.ExtMoment.initMoment().subtract(1, 'month').startOf('month'), $.ExtMoment.initMoment().subtract(1, 'month').endOf('month')]
                            };
                            break;
                        case "months":
                            dataJson={
                                '本月': [$.ExtMoment.initMoment().startOf('month'), $.ExtMoment.initMoment().endOf('month')],
                                '上月': [$.ExtMoment.initMoment().subtract(1, 'month').startOf('month'), $.ExtMoment.initMoment().subtract(1, 'month').endOf('month')],
                                '最近半年': [$.ExtMoment.initMoment().subtract(5, 'month').startOf('month'), $.ExtMoment.initMoment().endOf('month')],
                                '过去半年': [$.ExtMoment.initMoment().subtract(6, 'month').startOf('month'), $.ExtMoment.initMoment().subtract(1, 'month').endOf('month')],
                                '本年': [$.ExtMoment.initMoment().startOf('years'), $.ExtMoment.initMoment().endOf('years')]
                            };
                            break;
                        case "years":
                            dataJson={
                                '今年': [$.ExtMoment.initMoment().startOf('years'), $.ExtMoment.initMoment().endOf('years')],
                                '去年': [$.ExtMoment.initMoment().subtract(1, 'years').startOf('years'), $.ExtMoment.initMoment().subtract(1, 'years').endOf('years')]
                            };
                            break;
                    }
                    if(!$.ExtCommon.isCheckEmpty(option.removeQuick)){
                        $.each(option.removeQuick,function(i,r){if(dataJson.hasOwnProperty(r)){delete dataJson[r]}});
                    }
                    if(!$.ExtCommon.isCheckEmpty(option.addQuick)){
                        // $.each(option.addQuick,function(k,v){if(!dataJson.hasOwnProperty(k)){dataJson[k]=v}})
                        $.each(option.addQuick,function(k,v){dataJson[k]=v})
                    }
                }
                return dataJson;
            },
            initTimeFormat:function(value ,format){
                return $.ExtCommon.isCheckEmpty(value)?"":$.ExtMoment.initFormat({value:value,format:format})
            }
        };

        var datePickerExt = function(element, options) {
            var self=this;
            self.element = $(element);
            self.optionBase=$modalCommon.getOptions(self.element,options);
            self.elementOperate=new modalBase(this.element,this.optionBase);
            self.elementOperate.init();
        };
        datePickerExt.prototype = {
            getValue:function(){
                var value=this.elementOperate.getTextValue();
                switch (this.optionBase.type){
                    case "default":
                        if(!$.ExtCommon.isCheckEmpty(value)){
                            return $modalCommon.initTimeFormat(value,this.optionBase.formatOut)
                        }
                        break;
                    case "range":
                        var arrRange=[];
                        if (value.length > 0 && value.indexOf("~") > -1) {
                            var arrTemp = value.split("~");
                            if(arrTemp.length===2){
                                arrRange.push($modalCommon.initTimeFormat($.trim(arrTemp[0]),this.optionBase.formatOut));
                                arrRange.push($modalCommon.initTimeFormat($.trim(arrTemp[1]),this.optionBase.formatOut));
                            }
                        }
                        return arrRange;
                    default:
                        return ""
                }
            },
            setValue:function(start,end){
                this.elementOperate.setTextValue(start,end);
            },
            disabled:function(b){
                b= typeof b==="boolean"?b:true;
                b?this.elementOperate.disabledText():this.elementOperate.removeDisabledText()
            }
        };

        var modalBase=function (element,options) {
            this.element = element;
            this.options=options;
            switch (this.options.layerType){
                case "days":
                case "months":
                case "years":
                    this.options.layerView=this.options.layerType;
                    break;
                case "hours":
                case "minutes":
                case "seconds":
                    this.options.layerView=this.options.timeType==="datetime"?"days":"times";
                    break;
            }
            this.state={
                isOpen:false,
                value:this.options.initValue,
                startValue:this.options.startValue,
                endValue:this.options.endValue,
                currentView:this.options.layerView
            };
            if(this.options.type==="range"){
                this.state.value=this._getRangeValue();
            }
        };
        modalBase.prototype ={
            init:function () {
                this._bindElement();
                this._bindEvent();
                this._initText();
            },
            _bindElement:function () {
                var $templateHtml =$('<div class="time-parent"><div class="time-input-base"></div></div>');
                this.element.parent().append($templateHtml);
                this.element.prependTo($templateHtml.children(".time-input-base"));
                this.container={
                    parent:$templateHtml,
                    text:this.element
                };
                this.container.textParent=this.container.text.parent();
                this.container.textParent.append('<i class="fa fa-calendar"/>');
                this.container.text.prop("readonly",true).addClass("time-input");
                this.container.icon= this.container.text.next();
            },
            _bindEvent:function () {
                var self=this;
                self.container.text.off("click").on("click",function () {
                    self.state.isOpen?self._closeModal():self._openModal();
                });
                self.container.icon.off("click").on("click",function () {
                    var _this=$(this);
                    if(_this.hasClass("time-clear")){
                        switch(self.options.type){
                            case "default":
                                self._selectTimeCallback("");
                                break;
                            case "range":
                                self._selectTimeCallback({start:"",end:""});
                                break;
                        }

                    }else{
                        self.state.isOpen?self._closeModal():self._openModal();
                    }
                });
                self.container.parent.on("clickout",function () {
                    self._closeModal();
                });
            },
            _initText:function(){
                this.container.text.val(this.state.value);
                var isClear=this.options.isClear && !$.ExtCommon.isCheckEmpty(this.state.value);
                var isTime=this.options.timeType==="time";
                var cls="fa "+ $.ExtCommon.getArrByJsonBool({
                        "fa-close time-clear":isClear,
                        "fa-calendar":!isTime,
                        "fa-clock-o fa-lg":isTime
                    }).join(" ");
                this.container.icon.attr({
                    class:cls,
                    title:isClear?"清除":""
                });
            },
            _selectTimeCallback:function(data){
                var isChange=true;
                var oldState= $.ExtCommon.getJsonClone(this.state);
                switch(this.options.type){
                    case "default":
                        if(data!==this.state.value){
                            this.state.value=data;
                            this._initText(data);
                            isChange=this._operateChangeCallback(data);
                            if(!isChange){
                                this.state.value=oldState.value;
                                this._initText(oldState.value);
                            }
                        }
                        break;
                    case "range":
                        var start=data.start;
                        var end=data.end;
                        var rangeValue= this._getRangeValue(start,end);
                        if(rangeValue!==this.state.value){
                            this.state.startValue=start;
                            this.state.endValue=end;
                            this.state.value=rangeValue;
                            this._initText(rangeValue);
                            isChange=this._operateChangeCallback(data);
                            if(!isChange){
                                this.state.value=oldState.value;
                                this.state.startValue=oldState.startValue;
                                this.state.endValue=oldState.endValue;
                                this._initText(oldState.value);
                            }
                        }
                        break;
                }
                if(this.state.isOpen && isChange){this._closeModal()}
            },
            _operateChangeCallback:function(data){
                if(this.options.changeCallback){
                    var isChange;
                    switch(this.options.type){
                        case "default":
                            isChange=this.options.changeCallback(data);
                            break;
                        case "range":
                            isChange=this.options.changeCallback(data.start,data.end);
                            break;
                    }
                    isChange= typeof isChange === "boolean"?isChange:true;
                    return isChange;
                }else{
                    return true;
                }
            },
            _getRangeValue:function(start,end){
                start= $.ExtCommon.isCheckUndefined(start)?this.state.startValue:start;
                end=$.ExtCommon.isCheckUndefined(end)?this.state.endValue:end;
               return $.ExtCommon.isCheckEmpty(start)|| $.ExtCommon.isCheckEmpty(end)?"":(start+" ~ "+end);
            },
            _getViewProps:function(){
                var self=this;
                var options=$.ExtCommon.initMergeJson({},this.options);
                options.initValue=this.state.value;
                options.startValue=this.state.startValue;
                options.endValue=this.state.endValue;
                options.currentView=this.state.currentView;
                options.calendarValueCallback=function(dataValue){
                    self._selectTimeCallback(dataValue)
                };
                return options;
            },
            _openModal:function () {
                if(!this.state.isOpen){
                    this.state.isOpen=true;
                    var datepickerCls="datepicker datepicker-dropdown dropdown-menu datepicker-orient-"+this.options.direction+" datepicker-orient-bottom";
                    this.container.parent.addClass("time-open");
                    this.container.parent.append('<div class="'+datepickerCls+'"></div>');
                    this.container.calendar=this.container.parent.children(".datepicker");
                    var options=this._getViewProps();
                    this.calendar=null;
                    switch(this.options.type){
                        case "default":
                            this.calendar= new modalCalendarDefault(this.container.calendar,options);
                            break;
                        case "range":
                            this.calendar= new modalCalendarRange(this.container.calendar,options);
                            break;
                        default:
                            this.calendar= new modalCalendarDefault(this.container.calendar,options);
                            break;
                    }
                    this.calendar.init();
                }
            },
            _closeModal:function () {
                if(this.state.isOpen){
                    this.state.isOpen=false;
                    this.container.parent.removeClass("time-open");
                    if(this.container.calendar){
                        this.container.calendar.empty().remove();
                        this.container.calendar=null;
                    }
                    this.calendar=null;
                }
            },
            getTextValue:function(){
                return  $.trim(this.state.value);
            },
            setTextValue:function(start,end) {
                switch (this.options.type) {
                    case "default":
                        this.state.value=start;
                        break;
                    case "range":
                        this.state.startValue=start;
                        this.state.endValue=end;
                        this.state.value= this._getRangeValue(start,end);
                        break;
                }
                this._initText(this.state.value);
            },
            disabledText:function(){
                this.container.text.prop("disabled", true);
            },
            removeDisabledText:function(){
                this.container.text.prop("disabled", false);
            }
        };

        var modalCalendarRange=function (element,options) {
            this.element = element;
            this.options=options;
            this.state={
                count:0,
                startValue: $.ExtCommon.isCheckEmpty(this.options.startValue)?null:this.options.startValue,
                endValue:$.ExtCommon.isCheckEmpty(this.options.endValue)?null:this.options.endValue,
                timeStartValue:"",
                timeEndValue:""
            };
            var isStart=!$.ExtCommon.isCheckEmpty(this.state.startValue);
            var isEnd=!$.ExtCommon.isCheckEmpty(this.state.endValue);
            this.state.count=isStart&&isEnd?2:(isStart||isEnd?1:0);
            if(this.options.timeType==="time"){this.state.count=2}
            if(this.options.timeType==="datetime"){
                this.state.timeStartValue=(isStart? $.ExtMoment.initMoment(this.state.startValue,this.options.formatOut):$.ExtMoment.initMoment()).format("HH:mm:ss");
                this.state.timeEndValue=(isStart? $.ExtMoment.initMoment(this.state.endValue,this.options.formatOut):$.ExtMoment.initMoment()).format("HH:mm:ss");
            }

        };
        modalCalendarRange.prototype ={
            init:function(){
                var htmlText=this.options.timeType==="time"?'':'<div class="calendar-text"><div class="time-input-base"><input class="form-control time-input" type="text" readonly="readonly"><i class="fa fa-calendar"></i></div></div>';
                this.element.html('<div class="calendar-range calendar-left">'+htmlText+'<div class="calendar-panel"></div></div>' +
                    '<div class="calendar-range calendar-right">'+htmlText+'<div class="calendar-panel"></div></div>' +
                    '<div class="calendar-range calendar-quick"><ul></ul><div class="panel-quick-btn"><button class="quick-submit btn btn-sm btn-default" type="button">确定</button> <button class="quick-cancel btn btn-sm btn-gray-word" type="button">取消</button></div>');
                this.container={
                    leftText:this.element.find(">.calendar-left>.calendar-text :text"),
                    leftCalendar:this.element.find(">.calendar-left>.calendar-panel").first(),
                    rightText:this.element.find(">.calendar-right>.calendar-text :text"),
                    rightCalendar:this.element.find(">.calendar-right>.calendar-panel").first(),
                    quickPanel:this.element.find(">.calendar-quick >ul"),
                    quickSubmit:this.element.find(">.calendar-quick .quick-submit"),
                    quickCancel:this.element.find(">.calendar-quick .quick-cancel")
                };
                this.element.addClass("datepicker-range");
                this._initLeft();
                this._initRight();
                this._initText();
                this._initQuick();
                this._bindEvent();
                this._setQuickActive();
                this._setSubmitState();
            },
            _initLeft:function(){
                var self=this;
                var newOptions=this._getViewProps();
                if(!$.ExtCommon.isCheckEmpty(this.state.startValue)){
                    newOptions.initTimeValue= $.ExtMoment.initMoment(this.state.startValue,this.options.formatOut).format("HH:mm:ss")
                }
                newOptions.selectValueCallback=function(selectDate,layerView){
                    layerView==="times"
                        ?self._selectCalendarTimeCallback(selectDate,"left")
                        :self._selectCalendarCallback(selectDate)
                };
                newOptions.hoverValueCallback=function(hoverDate){self._hoverCalendarCallback(hoverDate)};
                newOptions.prevNextTimeCallback=function(viewDate){self._refreshCalendarView(self.calendarRight,self._updateTime("add",viewDate))};
                self.calendarLeft= new modalCalendar(this.container.leftCalendar,newOptions);
                self.calendarLeft.init()
            },
            _initRight:function(){
                var self=this;
                var newOptions=self._getViewProps();
                if(!$.ExtCommon.isCheckEmpty(this.state.endValue)){
                    newOptions.initTimeValue= $.ExtMoment.initMoment(this.state.endValue,this.options.formatOut).format("HH:mm:ss");
                    if(this.options.timeType==="time"){
                        newOptions.initValue=this.state.endValue
                    }
                }
                newOptions.selectValueCallback=function(selectDate,layerView){
                    layerView==="times"
                        ?self._selectCalendarTimeCallback(selectDate,"right")
                        :self._selectCalendarCallback(selectDate);
                };
                newOptions.hoverValueCallback=function(hoverDate){self._hoverCalendarCallback(hoverDate)};
                newOptions.prevNextTimeCallback=function(viewDate,isRestore){
                    if(isRestore){
                        self._refreshCalendarView(self.calendarLeft,viewDate.clone());
                        self._refreshCalendarView(self.calendarRight,self._updateTime("add",viewDate));
                    }else{
                        self._refreshCalendarView(self.calendarLeft,self._updateTime("subtract",viewDate))
                    }
                };
                self.calendarRight= new modalCalendar(this.container.rightCalendar,newOptions);
                self.calendarRight.init();
                self._refreshCalendarView(self.calendarRight,self._updateTime("add",self.calendarRight.state.viewDate));
            },
            _initText:function () {
                if(this.state.startValue){this.container.leftText.val(this.state.startValue)}
                if(this.state.endValue){this.container.rightText.val(this.state.endValue)}
            },
            _initQuick:function(){
                var self=this;
                self.container.quickPanel.children().empty().remove();
                if(!$.ExtCommon.isCheckEmpty(self.options.rangeQuick)){
                    $.each(self.options.rangeQuick,function (name,info) {
                        var liEl=$("<li>"+name+"</li>");
                        liEl.data("startEnd",info);
                        liEl.appendTo(self.container.quickPanel);
                    });
                    self.container.quickPanel.append("<li>自定义</li>");
                }
            },
            _bindEvent:function(){
                var self=this;
                self.container.quickPanel.children().off("click").on("click",function () {
                    var _thisEl=$(this);
                    var dataEl=_thisEl.data("startEnd");
                    if(dataEl){
                        self._cleanQuickActive();
                        _thisEl.addClass("active");
                        self.state.count=2;
                        self.state.startValue=dataEl[0].format(self.options.formatOut);
                        self.state.endValue=dataEl[1].format(self.options.formatOut);
                        self._selectValueCallback();
                        self._submit();
                    }
                });
                self.container.quickSubmit.off("click").on("click",function () {
                    self._submit();
                });
                self.container.quickCancel.off("click").on("click",function () {
                    self._calendarValueCallback(self.options.startValue,self.options.endValue)
                });
            },
            _getViewProps:function(){
                var arrExclude=[];
                var newOptions={};
                $.each(this.options,function(k,v){if(arrExclude.indexOf(k)===-1|| typeof v!=="function"){newOptions[k]=v}});
                if(this.state.startValue){newOptions.initValue=this.state.startValue}
                return newOptions;
            },
            _updateTime:function(type,viewDate){
                return $.ExtMoment.updateTime(type,viewDate,this.options.layerView==="years"?10:1,this.options.operateType)
            },
            _selectValueCallback:function(){
                if(this.state.count===1){
                    this.container.leftText.val(this.state.startValue);
                    this.container.rightText.val("");
                    this._refreshCalendarStart();
                    this._cleanQuickActive();
                }else if(this.state.count===2){
                    this.container.leftText.val(this.state.startValue);
                    this.container.rightText.val(this.state.endValue);
                    this._refreshCalendarEnd();
                    this._setQuickActive();
                }
                this._setSubmitState();
            },
            _selectCalendarTimeCallback:function(selectDate,type){
                type==="left"
                    ? (this.state.timeStartValue=selectDate)
                    :(this.state.timeEndValue=selectDate);
                if(this.state.count>0){
                    var tempDate=type==="left"?this.state.startValue:this.state.endValue;
                    if(!$.ExtCommon.isCheckEmpty(tempDate)){
                        var tempSelectValue=this._combinationCalendar(tempDate,selectDate);
                        type==="left"
                            ? (this.state.startValue=tempSelectValue)
                            :(this.state.endValue=tempSelectValue);
                        this._selectValueCallback()
                    }
                }
            },
            _combinationCalendar:function(date,time){
                var newValue=date;
                if(this.options.timeType==="datetime"){
                    if(!$.ExtCommon.isCheckEmpty(date)){
                        var tempDate=$.ExtMoment.initMoment(date, this.options.formatOut);
                        var timeDate=$.ExtMoment.initMoment(time, "HH:mm:ss");
                        tempDate.hours(timeDate.hours()).minutes(timeDate.minutes()).seconds(timeDate.seconds()).milliseconds(timeDate.milliseconds());
                        newValue=tempDate.format(this.options.formatOut);
                    }
                }
                return newValue;
            },
            _selectCalendarCallback:function(selectDate){
                var value=selectDate.format(this.options.formatOut);
                switch (this.state.count){
                    case 0:
                        this.state.count++;
                        this.state.startValue=this._combinationCalendar(value,this.state.timeStartValue);
                        break;
                    case 1:
                        if($.ExtMoment.initMoment(this.state.startValue, this.options.formatOut).isAfter(selectDate)){
                            this.state.startValue=this._combinationCalendar(value,this.state.timeStartValue);
                        }else{
                            this.state.count++;
                            this.state.endValue=this._combinationCalendar(value,this.state.timeEndValue);
                        }
                        break;
                    case 2:
                        this.state.count=1;
                        this.state.startValue=this._combinationCalendar(value,this.state.timeStartValue);
                        this.state.endValue=null;
                        break;
                }
                this._selectValueCallback()
            },
            _hoverCalendarCallback:function(hoverDate){
                if(this.state.count===1){
                    var isBefore=hoverDate.isBefore($.ExtMoment.initMoment(this.state.startValue,this.options.formatOut));
                    if(isBefore){
                        this.calendarLeft.cleanHoverDate();
                        this.calendarRight.cleanHoverDate();
                        this.container.rightText.val("");
                    }else{
                        this.calendarLeft.setHoverDate(hoverDate);
                        this.calendarRight.setHoverDate(hoverDate);
                        var value=this._combinationCalendar(hoverDate.format(this.options.formatOut),this.state.timeEndValue);
                        this.container.rightText.val(value);
                    }
                }
            },
            _refreshCalendarView:function(calendar,viewDate){
                calendar.refreshViewDate(viewDate);
            },
            _refreshCalendarStart:function(){
                this.calendarLeft.refreshRangeStart(this.state.startValue);
                this.calendarRight.refreshRangeStart(this.state.startValue);
            },
            _refreshCalendarEnd:function(){
                this.calendarLeft.refreshRangeEnd(this.state.startValue,this.state.endValue,true);
                this.calendarRight.refreshRangeEnd(this.state.startValue,this.state.endValue,false);
            },
            _setSubmitState:function(){
                this.container.quickSubmit.prop("disabled", this.state.count!==2);
            },
            _setQuickActive:function(){
                if(!$.ExtCommon.isCheckEmpty(this.state.startValue) &&
                    !$.ExtCommon.isCheckEmpty(this.state.endValue) &&
                    !$.ExtCommon.isCheckEmpty(this.options.rangeQuick))
                {
                    var self=this;
                    this._cleanQuickActive();
                    var startDate= $.ExtMoment.initMoment(this.state.startValue);
                    var endDate= $.ExtMoment.initMoment(this.state.endValue);
                    var ind=0;
                    $.each(this.options.rangeQuick,function (name,info) {
                        if(startDate.isSame(info[0].format(self.options.formatOut)) && endDate.isSame(info[1].format(self.options.formatOut))){return false}
                        ind++;
                    });
                    self.container.quickPanel.children().eq(ind).addClass("active");
                }
            },
            _cleanQuickActive:function(){
                this.container.quickPanel.find(".active").removeClass("active");
            },
            _submit:function(){
                if(this.state.count===2){
                    if(this.options.timeType==="time"){
                        var startTime= this.calendarLeft.getCalendarValue();
                        var endTime=this.calendarRight.getCalendarValue();
                        if($.ExtMoment.initMoment(startTime,"HH:mm:ss").isAfter($.ExtMoment.initMoment(endTime,"HH:mm:ss"))){
                            $.ExtNotify.destroy();
                            $.ExtNotify.error("时间范围选择不正确");
                        }else{
                            this.state.startValue=startTime;
                            this.state.endValue=endTime;
                            this.state.timeStartValue=startTime;
                            this.state.timeEndValue=endTime;
                            this._calendarValueCallback(startTime,endTime);
                        }
                    }else if(!$.ExtCommon.isCheckEmpty(this.state.startValue)&& !$.ExtCommon.isCheckEmpty(this.state.endValue)){
                        this._calendarValueCallback(this.state.startValue,this.state.endValue);
                    }
                }
            },
            _calendarValueCallback:function(start,end){
                if(this.options.calendarValueCallback){this.options.calendarValueCallback({start:start,end:end})}
            }
        };

        var modalCalendarDefault=function (element,options) {
            this.element = element;
            this.options=options;
            this.state={};
        };
        modalCalendarDefault.prototype ={
            init:function(){
                var newOptions=this._getViewProps();
                this.calendar= new modalCalendar(this.element,newOptions);
                this.calendar.init()
            },
            _getViewProps:function(){
                var self=this;
                var arrExclude=[];
                var newOptions={};
                $.each(this.options,function(k,v){if(arrExclude.indexOf(k)===-1|| typeof v!=="function"){newOptions[k]=v}});
                newOptions.selectValueCallback=function(selectDate){
                    var value=selectDate.format(self.options.formatOut);
                    if(self.options.calendarValueCallback){self.options.calendarValueCallback(value)}
                };
                return newOptions;
            }
        };

        var modalCalendar=function (element,options) {
            this.element = element;
            this.options=options;
            this.options.format="YYYY-MM-DD";
            switch (options.timeType){
                case "date":
                    this.options.format="YYYY-MM-DD";
                    break;
                case "datetime":
                    this.options.format="YYYY-MM-DD HH:mm:ss";
                    break;
                case "time":
                    this.options.format="HH:mm:ss";
                    break;
            }
            this.state={};
            var state=this._getInitState();
            this.state= $.ExtCommon.initMergeJson(state,{currentView:this.options.currentView})
        };
        modalCalendar.prototype ={
            init:function(){
                var options=this._getViewProps();
                switch (this.state.currentView){
                    case "years":
                        this.operateView=new modalYears(this.element,options);
                        break;
                    case "months":
                        this.operateView=new modalMonths(this.element,options);
                        break;
                    case "days":
                        this.operateView= new modalDays(this.element,options);
                        break;
                    case "times":
                        this.operateView= new modalTimes(this.element,options);
                        break;
                }
                if(this.operateView){this.operateView.init()}
            },
            _getInitState:function(){
                var formats = this._getFormats();
                var selectedDate=this._getMomentDate(this.options.initValue,formats);
                var viewDate = this._getViewDate(selectedDate,formats);
                var focusDate=viewDate.clone();
                var value=selectedDate?selectedDate.format(formats):"";
                var timeValue=this.options.initTimeValue;
                timeValue= !$.ExtCommon.isCheckEmpty(timeValue)?timeValue:(selectedDate?selectedDate.format("HH:mm:ss"): $.ExtMoment.initMoment().format("HH:mm:ss"));
                var startDate=this._getMomentDate(this.options.startValue,formats);
                var endDate=this._getMomentDate(this.options.endValue,formats);
                return {
                    format: formats,
                    focusDate:focusDate,
                    viewDate:viewDate,
                    selectedDate: selectedDate,
                    value: value,
                    timeValue:timeValue,
                    startDate:startDate,
                    endDate:endDate
                };
            },
            _getFormats:function(){
                var format="";
                if($.ExtCommon.isCheckUndefined(this.options.format)){
                    format=$.ExtMoment.initMoment.localeData().longDateFormat("L")+" "+$.ExtMoment.initMoment.localeData().longDateFormat("LTS");
                }else{
                    format=this.options.format;
                }
                return format
            },
            _getMomentDate:function(value,formats){
                var dateFormat;
                if(!$.ExtCommon.isCheckEmpty(value)){
                    var strFormats=formats||this.state.format;
                    if (value && typeof value === "string" ){dateFormat =$.ExtMoment.initMoment(value, strFormats)}
                    else if(value){  dateFormat = $.ExtMoment.initMoment(value)}
                    if (dateFormat && !dateFormat.isValid()){dateFormat = null}
                }
                return dateFormat;
            },
            _getViewDate:function(selected,formats){
                var strFormats=formats||this.state.format;
                var selectedDate=selected||($.ExtCommon.isCheckEmpty(this.state.value)?null:this._getMomentDate(this.state.value,strFormats));
                return selectedDate ? selectedDate.clone().startOf("month") : $.ExtMoment.initMoment().startOf("month");
            },
            _getViewProps:function(){
                var self=this;
                var options={
                    focusDate:this.state.focusDate,
                    viewDate:this.state.viewDate,
                    selectedDate:this.state.selectedDate,
                    startDate:this.state.startDate,
                    endDate:this.state.endDate,
                    type:this.options.type,
                    layerType:this.options.layerType,
                    timeType:this.options.timeType,
                    timeValue:this.state.timeValue
                };
                options.minDate=this._getMomentDate(this.options.minDate);
                options.maxDate=this._getMomentDate(this.options.maxDate);
                options.addTimeCallback=function(type,amount){self.addTime(type,amount)};
                options.subtractTimeCallback= function (type,amount){self.subtractTime(type,amount)};
                options.showViewCallback=function (view){self._showView(view)};
                switch (options.timeType){
                    case "date":
                    case "datetime":
                        options.selectCallback= function (target,type){self._calendarSelected(target,type)};
                        break;
                    case "time":
                        options.selectCallback= function (value){self._calendarSelectedTime(value)};
                        break;
                }
                options.hoverInCallback= function (target,type){self._calendarHoverIn(target,type)};
                options.checkMinMaxInCallback=function(value){return self._checkMinMaxIn(value)};
                return options;
            },
            _showView:function(view){
                this.state.currentView=view;
                this.state.focusDate= this.state.viewDate;
                this.init();
            },
            _calendarHoverIn:function(target,type){
                var hoverDate=this._getCalendarSelectDate(target,type);
                if(this.options.hoverValueCallback){this.options.hoverValueCallback(hoverDate)}
            },
            _getCalendarSelectedTime:function(value){
                var valueDate= $.ExtMoment.initMoment(value,"HH:mm:ss");
                var selectDate=this.state.viewDate.clone();
                selectDate.hours(valueDate.hours()).minutes(valueDate.minutes()).seconds(valueDate.seconds()).milliseconds(valueDate.milliseconds());
                return selectDate;
            },
            _calendarSelectedTime:function(value){
                var selectDate=this._getCalendarSelectedTime(value);
                var newValue=selectDate.format(this.state.format);
                if(this.options.timeType==="time"){
                    this._selectCallback(newValue,selectDate);
                }
            },
            _calendarSelected:function(target,viewType){
                if(viewType==="times"){
                    this.refreshState({timeValue:target});
                    if(this.options.type==="range"){
                        this._selectCallback(target,target,"times");
                    }
                }else{
                    var selectDate=this._getCalendarSelectDate(target,viewType);
                    var isLastLayer=this.options.layerView===viewType;
                    var newValue=selectDate.format(this.state.format);
                    var updState={ viewDate: selectDate.clone().startOf("month")};
                    updState.currentView=this._getNextViewByType(viewType);
                    if(isLastLayer){
                        if(this.options.type==="range"){
                            if(!this._checkSameView(viewType,selectDate)){
                                updState.selectedDate=selectDate;
                                updState.value=newValue;
                                if(viewType==="years"){updState.currentView="years"}
                                this.refreshState(updState);
                                this._prevNextCallback(this.state.viewDate,true);
                            }
                        }
                        this._selectCallback(newValue,selectDate);
                    }else{
                        if(viewType==="datetimes"){updState.selectedDate=selectDate}
                        this.refreshState(updState);
                        if(this.options.type==="range"){
                            if(updState.currentView===this.options.layerView){
                                this._prevNextCallback(this.state.viewDate);
                            }
                        }
                    }
                }
            },
            _getCalendarSelectDate:function(target,type){
                var modifier = 0,selectDate,
                    viewDate = this.state.viewDate,
                    currentDate = this.state.selectedDate || viewDate,
                    cls=target.attr("class"),
                    value=parseInt(target.data("value"),10);
                switch (type){
                    case "days":
                    case "datetimes":
                        if (cls.indexOf("new")>-1){ modifier = 1}
                        else if (cls.indexOf("old")>-1){ modifier = -1}
                        selectDate = viewDate.clone().month(viewDate.month() + modifier).date(value);
                        break;
                    case "months":
                        selectDate = viewDate.clone().month(value).date(currentDate.date());
                        break;
                    case "years":
                        selectDate = viewDate.clone().month(0).date(1).year(value);
                        break;
                }
                var tempTime= $.ExtMoment.initMoment(this.state.timeValue,"HH:mm:ss");
                selectDate.hours(tempTime.hours()).minutes(tempTime.minutes()).seconds(tempTime.seconds()).milliseconds(tempTime.milliseconds());
                return selectDate;
            },
            _getNextViewByType:function(type){
                var nextView="days";
                switch(type){
                    case "days":
                        nextView="days";
                        break;
                    case "months":
                        nextView="days";
                        break;
                    case "years":
                        nextView="months";
                        break;
                }
                return nextView;
            },
            _checkSameView:function(type,selectDate){
                var isCheck=true;
                switch(type){
                    case "days":
                        isCheck=selectDate.clone().startOf("month").isSame(this.state.viewDate.clone().startOf("month"));
                        break;
                    case "months":
                        isCheck=selectDate.clone().startOf("year").isSame(this.state.viewDate.clone().startOf("year"));
                        break;
                    case "years":
                        isCheck=parseInt(selectDate.year()/10,10)*10===parseInt(this.state.viewDate.year()/10,10)*10;
                        break;
                }
                return isCheck;
            },
            _checkMinMaxIn:function(value){
                var isIn=false;
                if(this.options.minDate){
                    isIn=$.ExtMoment.initMoment(value).isBefore(this.options.minDate);
                }
                if(!isIn && this.options.maxDate){
                    isIn=$.ExtMoment.initMoment(value).isAfter(this.options.maxDate);
                }
                return isIn;
            },
            _selectCallback:function(value,selectDate,layerView){
                layerView= $.ExtCommon.isCheckUndefined(layerView)?this.options.layerView:layerView;
                if(this.options.selectValueCallback){this.options.selectValueCallback(selectDate,layerView)}
            },
            _prevNextCallback:function(viewDate,isRestore){
                if(this.state.currentView===this.options.layerView){
                    isRestore=typeof isRestore==="boolean"?isRestore:false;
                    if(this.options.prevNextTimeCallback){this.options.prevNextTimeCallback(viewDate.clone(),isRestore)}
                }
            },
            addTime:function(type,amount){
                this._updateTime("add",type,amount);
            },
            subtractTime:function(type,amount){
                this._updateTime("subtract",type,amount);
            },
            _updateTime:function(operate,type,amount){
                this.state.viewDate =$.ExtMoment.updateTime(operate,this.state.viewDate,amount,type);
                this.init();
                this._prevNextCallback(this.state.viewDate);
            },
            refreshState:function(updState){
                this.state= $.ExtCommon.initMergeJson(this.state,updState);
                this.init();
            },
            refreshViewDate:function(viewDate){
                this.state.viewDate =viewDate.clone();
                this.state.currentView=this.options.layerView;
                this.init();
            },
            refreshSelectedDate:function(selectedValue){
                this.state.selectedDate =this._getMomentDate(selectedValue).clone();
                this.state.value=selectedValue;
                this.init();
            },
            refreshRangeStart:function(startValue){
                var startDate=this._getMomentDate(startValue);
                if(startDate){
                    this.state.selectedDate =null;
                    this.state.value="";
                    this.state.startDate =startDate.clone();
                    this.state.endDate = null;
                    this.init();
                }
            },
            refreshRangeEnd:function(startValue,endValue,isFirst){
                var startDate=this._getMomentDate(startValue);
                var endDate=this._getMomentDate(endValue);
                if(startDate && endDate){
                    this.state.selectedDate =null;
                    this.state.value="";
                    this.state.startDate =startDate.clone();
                    this.state.endDate = endDate.clone();
                    this.state.viewDate =isFirst?startDate.clone(): $.ExtMoment.addTime(startDate,this.options.layerView==="years"?10:1,this.options.operateType);
                    this.init();
                }
            },
            setHoverDate:function(hoverDate){
                this.operateView.setHoverDate(hoverDate.clone())
            },
            cleanHoverDate:function(){
                this.operateView.cleanHoverDate()
            },
            getCalendarValue:function(){
                var value="";
                switch (this.state.currentView){
                    case "years":
                        break;
                    case "months":
                        break;
                    case "days":
                        break;
                    case "times":
                        value=this.operateView.getTimeValue();
                        break;
                }
                return value;
            }
        };

        var modalDays=function (element,options) {
            this.element = element;
            this.options=options;
        };
        modalDays.prototype ={
            init:function(){
                this._isSameViewBySelect=false;
                if(this.options.viewDate && this.options.selectedDate){
                    this._isSameViewBySelect=this.options.viewDate.isSame(this.options.selectedDate,"months")
                }
                this.element.html('<div class="datepicker-days"><table class="datepicker-container"></table></div>');
                this.elementTable= this.element.find("table.datepicker-container");
                this._bindHead();
                this._bindBody();
                this._bindFoot();
            },
            _bindHead:function () {
                var date=this.options.viewDate,
                    locale = date.localeData(),
                    titleYear=date.year()+"年",
                    titleMonth=locale.months(date),
                    weeks=this._getHtmlWeek(locale).join(""),
                    prevYear=this._getHeadPrevYear(),
                    prevMonth=this._getHeadPrevMonth(),
                    nextYear=this._getHeadNextYear(),
                    nextMonth=this._getHeadNextMonth();
                this.elementTable.append('<thead><tr><th class="time-head time-head-day" colSpan="7">'+
                    '<span class="time-prev">'+prevYear+prevMonth+'</span>'+
                    '<span class="datepicker-switch-year">'+titleYear+'</span>'+
                    '<span class="datepicker-switch-month">'+titleMonth+'</span>'+
                    '<span class="time-next">'+nextYear+nextMonth+'</span>'+
                    '</th></tr><tr>'+weeks+'</tr></thead>');
                this._bindHeadEvent()
            },
            _bindHeadEvent:function () {
                var self=this;
                self.elementTable.find(">thead .prev-year").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.options.subtractTimeCallback("years",1)
                });
                self.elementTable.find(">thead  .prev-month").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.options.subtractTimeCallback("months",1)
                });
                self.elementTable.find(">thead  .next-year").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.options.addTimeCallback("years",1)
                });
                self.elementTable.find(">thead  .next-month").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.options.addTimeCallback("months",1)
                });
                self.elementTable.find(">thead  .datepicker-switch-year").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.options.showViewCallback("years")
                });
                self.elementTable.find(">thead  .datepicker-switch-month").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.options.showViewCallback("months")
                });
            },
            _getHeadPrevYear:function () {
                var prevYear = this.options.viewDate.clone().subtract(1, "years").endOf("month");
                var isDisabled=this.options.checkMinMaxInCallback(prevYear);
                return isDisabled?'':'<span class="prev-year" title="上一年"><i class="fa fa-angle-double-left"></i></span>'
            },
            _getHeadPrevMonth:function () {
                var prevMonth = this.options.viewDate.clone().subtract(1, "months").endOf("month");
                var isDisabled=this.options.checkMinMaxInCallback(prevMonth);
                return isDisabled?'':'<span class="prev-month"  title="上一月"><i class="fa fa-angle-left"></i></span>';
            },
            _getHeadNextYear:function(){
                var nextYear =this.options.viewDate.clone().add(1, "years").startOf("month");
                var isDisabled=this.options.checkMinMaxInCallback(nextYear);
                return isDisabled?'':'<span class="next-year"  title="下一年"><i class="fa fa-angle-double-right"></i></span>'
            },
            _getHeadNextMonth:function(){
                var nextMonth = this.options.viewDate.clone().add(1, "months").startOf("month");
                var isDisabled=this.options.checkMinMaxInCallback(nextMonth);
                return isDisabled?'':'<span class="next-month"  title="下一月"><i class="fa fa-angle-right"></i></span>';
            },
            _getHtmlWeek:function(locale){
                var days = locale["_weekdaysMin"], first = locale.firstDayOfWeek(), dow = [], di = 0;
                $.each(days,function(i,day){
                    dow[(7 + (di++) - first)%7] = day;
                });
                return $.map(dow,function(week){return '<th class="dow">'+week+'</th>'});
            },
            _bindBody:function(){
                var days=this._getHtmlDays().join("");
                this.elementTable.append('<tbody>'+days+'</tbody>');
                this._bindBodyEvent()
            },
            _bindBodyEvent:function(){
                var self=this;
                this.elementTable.find(">tbody td.day").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    var _this=$(this);
                    if(!_this.hasClass("disabled")){
                        var type="days";
                        if(self.options.timeType==="datetime"&& self.options.type==="default"){
                            type="datetimes";
                        }
                        self.options.selectCallback(_this,type);
                    }
                });
                this.elementTable.find(">tbody td.day").hover(function(){
                    var _this=$(this);
                    if(!_this.hasClass("disabled")){
                        self.options.hoverInCallback(_this,"days");
                    }
                },function(){})
            },
            _getHtmlDays:function(){
                var date = this.options.viewDate,
                    selected = this.options.selectedDate && this.options.selectedDate.clone(),
                    prevMonth = date.clone().subtract(1, "months"),
                    currentYear = date.year(),
                    currentMonth = date.month(),
                    weeks = [],
                    days = [];
                var rangeStart=this.options.startDate && this.options.startDate.clone(),
                    rangeEnd=this.options.endDate && this.options.endDate.clone();
                prevMonth.date(prevMonth.daysInMonth()).startOf("week");
                for(var i=0;i<42;i++){
                    if(i>0){prevMonth.add(1,"day")}
                    var currentDate = prevMonth.clone(),
                        currentValue=currentDate.date(),
                        isOld=(prevMonth.year() === currentYear && prevMonth.month() < currentMonth)||(prevMonth.year() < currentYear),
                        isNew=(prevMonth.year() === currentYear && prevMonth.month() > currentMonth)||(prevMonth.year() > currentYear),
                        isActive=selected && prevMonth.isSame(selected,"day"),
                        isDisabled = this.options.checkMinMaxInCallback(currentDate);
                    var isStart=false, isEnd=false,isRangeIn=false;
                    if(this.options.type==="range"){
                        isStart=rangeStart && prevMonth.isSame(rangeStart,"day");
                        isEnd=rangeEnd && prevMonth.isSame(rangeEnd,"day");
                        isActive=isStart||isEnd;
                        if(rangeStart&&rangeEnd){isRangeIn=prevMonth.isAfter(rangeStart,"day")&&prevMonth.isBefore(rangeEnd,"day")}
                    }
                    var cls="day "+ $.ExtCommon.getArrByJsonBool({
                            "old":isOld,
                            "new":isNew,
                            "active":isActive && !isOld && !isNew,
                            "disabled":isDisabled,
                            "date-start":isStart&& !isOld && !isNew,
                            "date-end":isEnd&& !isOld && !isNew,
                            "range-in":isRangeIn&& !isOld && !isNew
                        }).join(" ");
                    days.push($.ExtCommon.getStringConnect('<td class="{0}" data-value="{1}">{1}</td>',[cls,currentValue]));
                    if(days.length===7){
                        weeks.push('<tr>'+days.join("")+'</tr>');
                        days = [];
                    }
                }
                return weeks;
            },
            setHoverDate:function(hoverDate){
                var hoverDay=hoverDate.date();
                var lastDay=this.options.viewDate.clone().endOf("day");
                var hoverMonth=hoverDate.clone().startOf("month");
                var viewMonth=this.options.viewDate.clone().startOf("month");
                var isBefore=viewMonth.isBefore(hoverMonth);
                var isSame=viewMonth.isSame(hoverMonth);
                var tds=this.elementTable.find(">tbody td");
                var activeTd=tds.filter(".active");
                var activeValue=activeTd.length>0?parseInt(activeTd.first().data("value")):1;
                if(this.options.type==="range"){
                    if(viewMonth.isBefore(this.options.startDate.clone().startOf("month"))){
                        activeValue=-1;
                    }
                }
                if(activeValue>0){
                    tds.each(function(){
                        var _this=$(this);
                        _this.removeClass("range-in");
                        var thisDay=parseInt(_this.data("value"));
                        if(_this.hasClass("old") || _this.hasClass("new") || _this.hasClass("disabled")){}
                        else{
                            if(isBefore){if(thisDay>activeValue && thisDay<lastDay){ _this.addClass("range-in")}}
                            else if(isSame){if(thisDay>activeValue && thisDay<hoverDay){ _this.addClass("range-in")}}
                        }
                    });
                }else{
                    tds.removeClass("range-in");
                }
            },
            cleanHoverDate:function(){
                this.elementTable.find("td.range-in").removeClass("range-in")
            },
            _bindFoot:function(){
                if(this.options.timeType==="datetime"){
                    var foothtml='<div class="datepicker-days-times"></div>';
                    if(this.options.type==="default"){
                        var subCls="datepicker-days-submit "+$.ExtCommon.getArrByJsonBool({
                            "days-submit-disabled": !this._isSameViewBySelect
                        }).join(" ");
                        foothtml+=  '<div class="'+subCls+'"><span>确定</span></div>';
                    }
                    this.elementTable.after(foothtml);
                    this._bindFootEvent();
                    var time0ptions=this._getTimes0ptions();
                    this.timesView= new modalTimes(this.element.find(".datepicker-days-times"),time0ptions);
                    this.timesView.init();
                }
            },
            _bindFootEvent:function(){
                var self=this;
                this.element.find(".datepicker-days-submit").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    if(!$(this).hasClass("days-submit-disabled")&&self._isSameViewBySelect){
                        var _this= self.elementTable.find(".day.active");
                        if(_this.length>0){
                            if(!_this.hasClass("disabled")){
                                self.options.selectCallback(_this,"days");
                            }
                        }
                    }
                });
            },
            _getTimes0ptions:function(){
                var self=this;
                var options={};
                options.selectedDate=$.ExtMoment.initMoment(self.options.timeValue,"HH:mm:ss");
                options.type=this.options.type;
                options.timeType=this.options.timeType;
                options.layerType=this.options.layerType;
                options.isInitShow=false;
                options.isOverlayClick=true;
                options.selectCallback=function(value){
                    self.options.selectCallback(value,"times");
                };
                return options;
            }
        };

        var modalMonths=function (element,options) {
            this.element = element;
            this.options=options;
        };
        modalMonths.prototype ={
            init:function(){
                this.element.html('<div class="datepicker-months"><table class="datepicker-container"></table></div>');
                this.elementTable= this.element.find("table.datepicker-container");
                this._bindHead();
                this._bindBody()
            },
            _bindHead:function(){
                var date = this.options.viewDate,
                    titleYear=date.year()+"年",
                    prevYear=this._getHeadPrevYear(),
                    nextYear=this._getHeadNextYear();
                this.elementTable.append('<thead><tr><th class="time-head time-head-month">'+
                    '<span class="time-prev">'+prevYear+'</span>'+
                    '<span class="datepicker-switch-year">'+titleYear+'</span>'+
                    '<span class="time-next">'+nextYear+'</span>'+
                    '</th></tr></thead>');
                this._bindHeadEvent()
            },
            _bindHeadEvent:function(){
                var self=this;
                self.elementTable.find(">thead .prev-year").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.options.subtractTimeCallback("years",1)
                });
                self.elementTable.find(">thead  .next-year").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.options.addTimeCallback("years",1)
                });
                self.elementTable.find(">thead  .datepicker-switch-year").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.options.showViewCallback("years")
                });
            },
            _getHeadPrevYear:function(){
                var prevYear = this.options.viewDate.clone().subtract(1, "years").endOf("month");
                var isDisabled=this.options.checkMinMaxInCallback(prevYear);
                return isDisabled?'':'<span class="prev-year"  title="上一年"><i class="fa fa-angle-left"></i></span>'
            },
            _getHeadNextYear:function(){
                var nextYear =this.options.viewDate.clone().add(1, "years").startOf("month");
                var isDisabled=this.options.checkMinMaxInCallback(nextYear);
                return isDisabled?'':'<span class="next-year"  title="下一年"><i class="fa fa-angle-right"></i></span>';
            },
            _bindBody:function(){
                var months=this._getHtmlMonths();
                this.elementTable.append('<tbody><tr><td class="time-body-month">'+months.join("")+'</td></tr></tbody>');
                this._bindBodyEvent()
            },
            _bindBodyEvent:function(){
                var self=this;
                self.elementTable.find(">tbody .month").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    var _this=$(this);
                    if(!_this.hasClass("disabled")){
                        self.options.selectCallback(_this,"months");
                    }
                });
                self.elementTable.find(">tbody .month").hover(function(){
                    var _this=$(this);
                    if(!_this.hasClass("disabled")){self.options.hoverInCallback(_this,"months")}
                },function(){})
            },
            _getHtmlMonths:function(){
                var self=this;
                var date = self.options.viewDate,
                    focus=self.options.focusDate && self.options.focusDate.clone(),
                    selected = self.options.selectedDate && self.options.selectedDate.clone(),
                    currentYear = date.year();
                var rangeStart=this.options.startDate && this.options.startDate.clone(),
                    rangeEnd=this.options.endDate && this.options.endDate.clone();
                return $.map(date.localeData()["_months"],function(m,i){
                    var tempData = self._getMonthByMin(currentYear,i),
                        isActive=selected && tempData.isSame(selected,"month"),
                        isFocused=tempData.isSame(focus,"month"),
                        isDisabled = self.options.checkMinMaxInCallback(tempData);
                    var isStart=false, isEnd=false,isRangeIn=false;
                    if(self.options.type==="range"){
                        isFocused=false;
                        isStart=rangeStart && tempData.isSame(rangeStart,"month");
                        isEnd=rangeEnd && tempData.isSame(rangeEnd,"month");
                        isActive=isStart||isEnd;
                        if(rangeStart&&rangeEnd){isRangeIn=tempData.isAfter(rangeStart,"month")&&tempData.isBefore(rangeEnd,"month")}
                    }
                    if(self.options.layerType==="months"){isFocused=false}
                    var cls="month "+ $.ExtCommon.getArrByJsonBool({
                            "active":isActive,
                            "focused":isFocused,
                            "disabled":isDisabled,
                            "date-start":isStart,
                            "date-end":isEnd,
                            "range-in":isRangeIn
                        }).join(" ");
                    return $.ExtCommon.getStringConnect('<span class="{0}" data-value="{1}">{2}</span>',[cls,i,m])
                });
            },
            _getMonthByMin:function(y,m){
                var d=1;
                if(this.options.minDate){
                    d=y===this.options.minDate.year()&&m===this.options.minDate.month()?this.options.minDate.date():1;
                }
                return  $.ExtMoment.initMoment({year:y,month:m,day:d})
            },
            setHoverDate:function(hoverDate){
                var hoverMonth=hoverDate.month();
                var lastMonth=12;
                var hoverYear=hoverDate.clone().startOf("year");
                var viewYear=this.options.viewDate.clone().startOf("year");
                var isSame=viewYear.isSame(hoverYear);
                var isBefore=viewYear.isBefore(hoverYear);
                var spMonths=this.elementTable.find(">tbody .month");
                var activeTd=spMonths.filter(".active");
                var activeValue=activeTd.length>0?parseInt(activeTd.first().data("value")):-1;
                if(this.options.type==="range"){
                    if(viewYear.isBefore(this.options.startDate.clone().startOf("year"))){
                        activeValue=-2;
                    }
                }
                if(activeValue>-2){
                    spMonths.each(function(){
                        var _this=$(this);
                        _this.removeClass("range-in");
                        var thisMonth=parseInt(_this.data("value"));
                        if(_this.hasClass("disabled")){}
                        else{
                            if(isBefore){if(thisMonth>activeValue && thisMonth<lastMonth){ _this.addClass("range-in")}}
                            else if(isSame){if(thisMonth>activeValue && thisMonth<hoverMonth){ _this.addClass("range-in")}}
                        }
                    });
                }else{
                    spMonths.removeClass("range-in")
                }
            },
            cleanHoverDate:function(){
                this.elementTable.find("span.range-in").removeClass("range-in")
            }
        };

        var modalYears=function (element,options) {
            this.element = element;
            this.options=options;
        };
        modalYears.prototype ={
            init:function(){
                this._startYear=parseInt(this.options.viewDate.year()/10,10)*10;
                this.element.html('<div class="datepicker-years"><table class="datepicker-container"></table></div>');
                this.elementTable= this.element.find("table.datepicker-container");
                this._bindHead();
                this._bindBody()
            },
            _bindHead:function(){
                var titleYear= this._startYear+"-"+(this._startYear+9),
                    prevYear=this._getHeadPrevYear(),
                    nextYear=this._getHeadNextYear();
                this.elementTable.append('<thead><tr><th class="time-head time-head-year">'+
                    '<span class="time-prev">'+prevYear+'</span>'+
                    '<span class="">'+titleYear+'</span>'+
                    '<span class="time-next">'+nextYear+'</span>'+
                    '</th></tr></thead>');
                this._bindHeadEvent()
            },
            _bindHeadEvent:function(){
                var self=this;
                self.elementTable.find(">thead .prev-year").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.options.subtractTimeCallback("years",10)
                });
                self.elementTable.find(">thead  .next-year").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.options.addTimeCallback("years",10)
                });
            },
            _getHeadPrevYear:function(){
                var prevYear=$.ExtMoment.initMoment({year:this._startYear-1,month:11}).endOf("month");
                var isDisabled=this.options.checkMinMaxInCallback(prevYear);
                return isDisabled?'':'<span class="prev-year"  title="前十年"><i class="fa fa-angle-left"></i></span>'
            },
            _getHeadNextYear:function(){
                var nextYear =$.ExtMoment.initMoment({year:this._startYear+10,month:0}).startOf("month");
                var isDisabled=this.options.checkMinMaxInCallback(nextYear);
                return isDisabled?'':'<span class="next-year" title="后十年"><i class="fa fa-angle-right"></i></span>'
            },
            _bindBody:function(){
                var years=this._getHtmlYears();
                this.elementTable.append('<tbody><tr><td class="time-body-year">'+years.join("")+'</td></tr></tbody>');
                this._bindBodyEvent()
            },
            _bindBodyEvent:function(){
                var self=this;
                self.elementTable.find(">tbody .year").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    var _this=$(this);
                    if(!_this.hasClass("disabled")){
                        self.options.selectCallback(_this,"years");
                    }
                });
                self.elementTable.find(">tbody .year").hover(function(){
                    var _this=$(this);
                    if(!_this.hasClass("disabled")){self.options.hoverInCallback(_this,"years")}
                },function(){})
            },
            _getHtmlYears:function(){
                var focus=this.options.focusDate && this.options.focusDate.clone(),
                    selected = this.options.selectedDate && this.options.selectedDate.clone(),
                    arrYear=[];
                var rangeStart=this.options.startDate && this.options.startDate.clone(),
                    rangeEnd=this.options.endDate && this.options.endDate.clone();
                for(var i=-1;i<11;i++){
                    var tempYear=this._startYear+i,
                        tempData =this._getYearByMin(tempYear),
                        isOld=i===-1, isNew=i>9,
                        isActive=selected && tempData.isSame(selected,"year"),
                        isFocused=tempData.isSame(focus,"year"),
                        isDisabled = this.options.checkMinMaxInCallback(tempData);
                    var isStart=false, isEnd=false,isRangeIn=false;
                    if(this.options.type==="range"){
                        isFocused=false;
                        isStart=rangeStart && tempData.isSame(rangeStart,"year");
                        isEnd=rangeEnd && tempData.isSame(rangeEnd,"year");
                        isActive=isStart||isEnd;
                        if(rangeStart&&rangeEnd){isRangeIn=tempData.isAfter(rangeStart,"year")&&tempData.isBefore(rangeEnd,"year")}
                    }
                    if(this.options.layerType==="year"){isFocused=false}
                    var cls="year "+ $.ExtCommon.getArrByJsonBool({
                            "old":isOld,
                            "new":isNew,
                            "active":isActive&& !isOld && !isNew,
                            "focused":isFocused,
                            "disabled":isDisabled,
                            "date-start":isStart&& !isOld && !isNew,
                            "date-end":isEnd&& !isOld && !isNew,
                            "range-in":isRangeIn&& !isOld && !isNew
                        }).join(" ");
                    arrYear.push($.ExtCommon.getStringConnect('<span class="{0}" data-value="{1}">{1}</span>',[cls,tempYear]));
                }
                return arrYear;
            },
            _getYearByMin:function(y){
                var m= 0,d=1;
                if(this.options.minDate){
                    var isMinYear=y===this.options.minDate.year();
                    m=isMinYear?this.options.minDate.month():0;
                    d=isMinYear?this.options.minDate.date():1;
                }
                return  $.ExtMoment.initMoment({year:y,month:m,day:d})
            },
            setHoverDate:function(hoverDate){
                var hoverYear=hoverDate.year();
                var hoverYear10=parseInt(hoverYear/10,10)*10;
                var viewYear=this._startYear;
                var lastYear=viewYear+9;
                var isSame=viewYear===hoverYear10;
                var isBefore=viewYear<hoverYear10;
                var spYears=this.elementTable.find(">tbody .year");
                var activeTd=spYears.filter(".active");
                var activeValue=activeTd.length>0?parseInt(activeTd.first().data("value")):viewYear;
                if(this.options.type==="range"){
                    if(lastYear<this.options.startDate.year()){
                        activeValue=-1;
                    }
                }
                if(activeValue>-1){
                    spYears.each(function(){
                        var _this=$(this);
                        _this.removeClass("range-in");
                        var thisYear=parseInt(_this.data("value"));
                        if(_this.hasClass("old") || _this.hasClass("new") || _this.hasClass("disabled")){}
                        else{
                            if(isBefore){if(thisYear>=activeValue && thisYear<=lastYear){ _this.addClass("range-in")}}
                            else if(isSame){if(thisYear>=activeValue && thisYear<=hoverYear){ _this.addClass("range-in")}}
                        }
                    });
                }else{
                    spYears.removeClass("range-in");
                }
            },
            cleanHoverDate:function(){
                this.elementTable.find("span.range-in").removeClass("range-in")
            }
        };

        var modalTimes=function (element,options) {
            this.element = element;
            this.options=options;
            this.options.isOverlayClick=$.ExtCommon.isCheckBoolean(this.options.isOverlayClick)?this.options.isOverlayClick:false;
            var nowMoment= this.options.selectedDate?this.options.selectedDate.clone():$.ExtMoment.initMoment();
            var HH=$.ExtCommon.fillZero(nowMoment.hours());
            var mm=$.ExtCommon.fillZero(nowMoment.minutes());
            var ss=$.ExtCommon.fillZero(nowMoment.seconds());
            this._initClockOperate={hour:false,minute:false,second:false};
            switch (this.options.layerType){
                case "hours":
                    this._initClockOperate.hour=true;
                    mm="00";
                    ss="00";
                    break;
                case "minutes":
                    this._initClockOperate.hour=true;
                    this._initClockOperate.minute=true;
                    ss="00";
                    break;
                case "seconds":
                    this._initClockOperate.hour=true;
                    this._initClockOperate.minute=true;
                    this._initClockOperate.second=true;
                    break
            }
            this._timeAngle={hour:30,minute:6,second:6};
            this.state={
                original:{hour:HH,minute:mm,second:ss},
                rotate:{hour:-90,hourMinute:0,minute:-90,minuteSecond:0,second:-90},
                oldValue:{hour:"0",minute:"0",second:"0"},
                newValue:{hour:HH,minute:mm,second:ss},
                isClockShow: $.ExtCommon.isCheckBoolean(this.options.isInitShow)?this.options.isInitShow:true
            };
            if(this.options.txtDisabled){
                setTimeout(function(){$(".daterangepicker :text.input-mini").prop("disabled", true);},300);
            }
        };
        modalTimes.prototype ={
            init:function(){
                var isOpen=this.state.isClockShow?"times-open":"";
                this.element.html('<div class="datepicker-times '+isOpen+'"><div class="datepicker-times-inner"></div><div class="datepicker-container"><div class="times-container"></div></div></div>');
                this.elementBase=this.element.children(".datepicker-times");
                this.elementContainer= this.element.find(".datepicker-container");
                this.elementTimes= this.element.find(".times-container");
                this._bindBody();
                this._bindFoot();
                this._setClock("hour");
                this._setPointerRotate();
            },
            _bindBody:function(){
                var hourDisabled=this._initClockOperate.hour?"":"pointer-disabled";
                var minuteDisabled=this._initClockOperate.minute?"":"pointer-disabled";
                var secondDisabled=this._initClockOperate.second?"":"pointer-disabled";
                this.elementTimes.append('<div class="times-overlay"></div>');
                this.elementTimes.append(this.options.type==="range"&&this.options.timeType==="time"?"":'<div class="times-submit" title="确定"><i class="fa fa-check fa-lg text-success"></i></div>');
                this.elementTimes.append('<div class="times-clock">' +
                    '<div class="clock-nums">' +
                        '<div class="clock-num" style="left: 50%; top: 0;">0</div>' +
                        '<div class="clock-num" style="left: 75%; top: 6.7%;">1</div>' +
                        '<div class="clock-num" style="left: 93.3%; top: 25%;">2</div>' +
                        '<div class="clock-num" style="left: 100%; top: 50%;">3</div>' +
                        '<div class="clock-num" style="left: 93.3%; top: 75%;">4</div>' +
                        '<div class="clock-num" style="left: 75%; top: 93.3%;">5</div>' +
                        '<div class="clock-num" style="left: 50%; top: 100%;">6</div>' +
                        '<div class="clock-num" style="left: 25%; top: 93.3%;">7</div>' +
                        '<div class="clock-num" style="left: 6.7%; top: 75%;">8</div>' +
                        '<div class="clock-num" style="left: 0; top: 50%;">9</div>' +
                        '<div class="clock-num" style="left: 6.7%; top: 25%;">10</div>' +
                        '<div class="clock-num" style="left: 25%; top: 6.7%;">11</div>' +
                    '</div>' +
                    '<div class="clock-pointer">' +
                        '<div class="pointer-hour pointer-active '+hourDisabled+'" data-type="hour" style="transform: rotate(-90deg);"></div>' +
                        '<div class="pointer-minute  '+minuteDisabled+'" data-type="minute" style="transform: rotate(-90deg);"></div>' +
                        '<div class="pointer-second  '+secondDisabled+'" data-type="second" style="transform: rotate(-90deg);"></div>' +
                    '</div>' +
                    '<div class="clock-am"><small class="am-am am-active" data-type="am">AM</small><small class="am-pm" data-type="pm">PM</small></div>' +
                    '</div>');
                this._bindBodyEvent();
            },
            _bindBodyEvent:function(){
                var self=this;
                self.elementTimes.find(".times-overlay").off("click").on("click",function () {
                    if(self.options.isOverlayClick){
                        self.elementBase.removeClass("times-open");
                        if(self.state.newValue.hour!==self.state.original.hour
                            || self.state.newValue.minute!==self.state.original.minute
                            || self.state.newValue.second!==self.state.original.second)
                        {
                            self.state.oldValue.hour=self.state.newValue.hour;
                            self.state.oldValue.minute=self.state.newValue.minute;
                            self.state.oldValue.second=self.state.newValue.second;
                            self.state.newValue.hour=self.state.original.hour;
                            self.state.newValue.minute=self.state.original.minute;
                            self.state.newValue.second=self.state.original.second;
                            self._setClockSetText("hour",self.state.original.hour);
                            self._setClockSetText("minute",self.state.original.minute);
                            self._setClockSetText("second",self.state.original.second);
                            self._setPointerRotate();
                        }
                    }
                });
                self.elementTimes.find(".times-submit").off("click").on("click",function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.elementBase.removeClass("times-open");
                    var value= self.getTimeValue();
                    if(self.options.selectCallback){self.options.selectCallback(value);}
                });
                self.elementTimes.find(".clock-nums>div").off("click").on("click",function () {
                    var type=self.elementTimes.find(".clock-pointer>.pointer-active").data("type");
                    var oldValue=parseInt(self._getValueByType(type));
                    var newValue=parseInt($.trim($(this).text()));
                    if(newValue!==oldValue){
                        self._setClockSetValue(type,newValue);
                        self._setPointerRotate();
                    }
                });
                self.elementTimes.find(".clock-pointer>div").off("click").on("click",function () {
                    var thisEl=$(this);
                    var type=thisEl.data("type");
                    if(!thisEl.hasClass("pointer-active")&& !thisEl.hasClass("clock-set-disabled") && self._initClockOperate[type]){
                        self._setClock(type);
                    }
                });
                self.elementTimes.find(".clock-am>small").off("click").on("click",function () {
                    var type=$(this).data("type");
                    self._setClockAm("hour",type);
                    self._setClockNum("hour");
                });
            },
            _bindFoot:function(){
                var hourDisabled=this._initClockOperate.hour?"":"clock-set-disabled";
                var minuteDisabled=this._initClockOperate.minute?"":"clock-set-disabled";
                var secondDisabled=this._initClockOperate.second?"":"clock-set-disabled";
                this.elementContainer.append('<div class="clock-set clock-set-hour clock-set-active '+hourDisabled+'" data-type="hour"><div><span class="value-hour">'+this.state.newValue.hour+'</span><a class="clock-set-sub" href="javascript:"><i class="fa fa-angle-up"></i></a><a class="clock-set-add" href="javascript:"><i class="fa fa-angle-down"></i></a></div></div>');
                this.elementContainer.append('<div class="clock-set clock-set-minute '+minuteDisabled+'" data-type="minute"><div><span class="value-minute">'+this.state.newValue.minute+'</span><a class="clock-set-sub" href="javascript:"><i class="fa fa-angle-up"></i></a><a class="clock-set-add" href="javascript:"><i class="fa fa-angle-down"></i></a></div></div>');
                this.elementContainer.append('<div class="clock-set clock-set-second '+secondDisabled+'" data-type="second"><div><span class="value-second">'+this.state.newValue.second+'</span><a class="clock-set-sub" href="javascript:"><i class="fa fa-angle-up"></i></a><a class="clock-set-add" href="javascript:"><i class="fa fa-angle-down"></i></a></div></div>');
                this._bindFootEvent();
            },
            _bindFootEvent:function(){
                var self=this;
                self.elementContainer.find(".clock-set").off("click").on("click",function () {
                    if(!self.elementBase.hasClass("times-open")){
                        self.elementBase.addClass("times-open");
                    }
                    var thisEl=$(this);
                    var type=thisEl.data("type");
                    if(!thisEl.hasClass("clock-set-active") && !thisEl.hasClass("clock-set-disabled")  && self._initClockOperate[type]){self._setClock(type)}
                });
                self.elementContainer.find(".clock-set .clock-set-sub").off("click").on("click",function (e) {
                    self._operateClockSet(e,"sub");
                });
                self.elementContainer.find(".clock-set .clock-set-add").off("click").on("click",function (e) {
                    self._operateClockSet(e,"add");
                });
            },
            _setClock:function(type){
                this._setClockAm(type);
                this._setPointerActive(type);
                this._setClockSetActive(type);
                this._setClockNum(type);
            },
            _setClockNum:function(type){
                var nums=[];
                switch(type){
                    case "hour":
                        var amType= this.elementTimes.find(".clock-am>.am-active").data("type");
                        nums=amType==="am"?[0,1,2,3,4,5,6,7,8,9,10,11]:[12,13,14,15,16,17,18,19,20,21,22,23];
                        break;
                    case "minute":
                    case "second":
                        nums=[0,5,10,15,20,25,30,35,40,45,50,55];
                        break;
                }
                $.each(this.elementTimes.find(".clock-nums").children(),function(i,item){
                    $(item).text(nums[i]);
                });
            },
            _setPointerRotate:function(){
                this._setRotateHour();
                this._setRotateMinute();
                this._setRotateSecond();
                this.elementTimes.find(".pointer-hour").css("transform","rotate("+(this.state.rotate.hour+this.state.rotate.hourMinute)+"deg)");
                this.elementTimes.find(".pointer-minute").css("transform","rotate("+(this.state.rotate.minute+ this.state.rotate.minuteSecond)+"deg)");
                this.elementTimes.find(".pointer-second").css("transform","rotate("+(this.state.rotate.second)+"deg)");
            },
            _setRotateHour:function(){
                this.state.rotate.hour=this._calculateRotate("hour");
                var valueMinute=parseInt(this.state.newValue.minute);
                this.state.rotate.hourMinute=this._timeAngle.hour*(parseFloat(valueMinute/60));
            },
            _setRotateMinute:function(){
                this.state.rotate.minute=this._calculateRotate("minute");
                var valueSecond=parseInt(this.state.newValue.second);
                this.state.rotate.minuteSecond=this._timeAngle.second*(parseFloat(valueSecond/60));
            },
            _setRotateSecond:function(){
                this.state.rotate.second=this._calculateRotate("second");
            },
            _calculateSkipCount:function(type){
                var valueOld=parseInt(this.state.oldValue[type]);
                var valueNew=parseInt(this.state.newValue[type]);
                var skip=0;
                if(type==="hour"){
                    if(valueNew===0&&valueOld===23){valueNew=24}
                    if(valueOld===0&&valueNew===23){valueOld=24}
                    if(valueNew-valueOld>6){valueOld+=12}
                    if(valueOld-valueNew>=6){valueNew+=12}
                    skip=valueNew-valueOld
                }else{
                    if(valueNew-valueOld>30){valueOld+=60}
                    if(valueOld-valueNew>=30){valueNew+=60}
                    skip=valueNew-valueOld;
                }
                return skip;
            },
            _calculateRotate:function(type){
                var skip=this._calculateSkipCount(type);
                var angle=skip*this._timeAngle[type];
                return this.state.rotate[type]+(angle>=360?(angle%360):angle);
            },
            _setPointerActive:function(type){
                var el=this.elementTimes.find(".clock-pointer>.pointer-"+type);
                if(!el.hasClass("pointer-active")){
                    el.siblings().removeClass("pointer-active");
                    el.addClass("pointer-active");
                }
            },
            _setClockAm:function(type,operateType){
                var el=this.elementTimes.find(">.times-clock>.clock-am");
                el.toggle(type==="hour");
                if(type==="hour"){
                    if($.ExtCommon.isCheckUndefined(operateType)){
                        operateType=this._getClockAmValue();
                    }
                    el.find(".am-active").removeClass("am-active");
                    el.find(".am-"+operateType).addClass("am-active");
                }
            },
            _getClockAmValue:function(){
                var hourValue=parseInt(this._getValueHour());
                return hourValue<12?"am":"pm";
            },
            _setClockSetActive:function(type){
                var el=this.elementContainer.find(".clock-set.clock-set-"+type);
                if(!el.hasClass("clock-set-active")){
                    el.siblings().removeClass("clock-set-active");
                    el.addClass("clock-set-active");
                }
            },
            _operateClockSet:function(e,operateType){
                e.preventDefault();
                e.stopPropagation();
                var pEl=$(e.currentTarget).parents(".clock-set").first();
                var type=pEl.data("type");
                if(this.elementBase.hasClass("times-open")){
                    if(!pEl.hasClass("clock-set-disabled") && this._initClockOperate[type]){
                        this._calculateClockSetValue(pEl,type,operateType);
                        if(pEl.hasClass("clock-set-active")){
                            if(type==="hour"){
                                var amType=this._getClockAmValue();
                                var currentAm=this.elementTimes.find(".clock-am>.am-active").data("type");
                                if(amType!==currentAm){
                                    this._setClockAm("hour");
                                    this._setClockNum("hour");
                                }
                            }
                        }else{
                            this._setClock(type);
                        }
                        this._setPointerRotate();
                    }
                }else{
                    this.elementBase.addClass("times-open");
                    this._setClock(type);
                }
            },
            _calculateClockSetValue:function(parentEl,type,operateType){
                var valueEl=parentEl.find(".value-"+type).first();
                var value=parseInt(valueEl.text());
                var max=type==="hour"?23:59;
                var newValue=0;
                if(operateType==="add"){
                    newValue=value===max?0:(value+1)
                }else{
                    newValue=value===0?max:(value-1);
                }
                this._setClockSetValue(type,newValue)
            },
            _setClockSetValue:function(type,value){
                this.state.oldValue.hour=this._getValueHour();
                this.state.oldValue.minute=this._getValueMinute();
                this.state.oldValue.second=this._getValueSecond();
                var newValue= $.ExtCommon.fillZero(value);
                this.state.oldValue[type]=this._getValueByType(type);
                this.state.newValue[type]=newValue;
                this._setClockSetText(type,newValue)
            },
            _setClockSetText:function(type,newValue){
                var el=this.elementContainer.find(".clock-set .value-"+type);
                el.text(newValue);
            },
            _getValueHour:function(){
                return this._getValueByType("hour");
            },
            _getValueMinute:function(){
                return this._getValueByType("minute");
            },
            _getValueSecond:function(){
                return this._getValueByType("second");
            },
            _getValueByType:function(type){
                return $.trim(this.elementContainer.find(".clock-set-"+type+" .value-"+type).text());
            },
            getTimeValue:function(){
                return this.state.newValue.hour+":"+this.state.newValue.minute+":"+this.state.newValue.second;
            }
        };

        $.fn.ExtDatePicker= function(options) {
            var dataFun;
            this.each(function() {
                var el = $(this);
                var tempData=el.data('ExtDatePicker');
                if (tempData) {
                    if (typeof  options === "string") {
                        if (tempData[options]) {
                            dataFun =tempData[options]()
                        } else {
                            dataFun = tempData
                        }
                    } else {
                        dataFun = tempData
                    }
                } else {
                    dataFun = new datePickerExt(el, options);
                    el.data('ExtDatePicker', dataFun);
                }
            });
            return dataFun;
        };
    })
);